import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.Date;

import sun.net.www.protocol.http.HttpURLConnection;


public class BlockDownloader extends Thread {
	String url;
	char fName;
	long total, partial,readed;
	boolean completed = false;
	InputStream inputStream;
	OutputStream stream;
	boolean reStart=false;
	Downloader downloader;
	static int blockL=1024*2;
	File file;
	FileChannel channel;
	public BlockDownloader(Downloader downloader,String url, char fName, long partial, long total) {
		this.downloader=downloader;
		this.fName = fName;
		this.url = url;
		this.partial = partial;
		this.total = total;
		this.file = downloader.file;
		this.channel=downloader.channel;
		readed=downloader.getBpr(fName);
	}
	char getFname(){
		return fName;
	}
	public void run() {
		int count = 0;
		aging: while (true) {
			
			try {
				if (count > 0)
					System.out.println(fName + " reStart. ");
				long unReadLen= total- readed;
//				System.out.println(fName+" "+total+" "+unReadLen+" "+ file.length());
				if (unReadLen <= 0) {
					completed = true;
					downloader.complete(fName);
					return;
				}
				URL u=new URL(url);
				URLConnection connection =u.openConnection();
			
				String property = "bytes=" + (partial + readed) + "-";
				connection.setRequestProperty("RANGE", property);
				connection.setRequestProperty("User-Agent","Xbox Live Client/2.0.14719.0");
				connection.setRequestProperty("Host",u.getHost());
				int responseCode = ((HttpURLConnection)connection).getResponseCode();
				if(responseCode>499)throw new RuntimeException("net connect Error ResponseCode "+responseCode);

				inputStream = connection.getInputStream();
				ReadableByteChannel newChannel = Channels
						.newChannel(inputStream);
				System.out.println(fName + " start time:"
						+ new Date().toLocaleString());
				long position = partial+readed;
				long len = 0;
				int allocate=unReadLen>=blockL?blockL:(int)unReadLen;
				ByteBuffer buffer=ByteBuffer.allocate(allocate);
				
				while ( unReadLen>0) {
				//	System.out.println(len+" inputStream.available():"+inputStream.available());
					len = newChannel.read(buffer);
					if (len < 1 && unReadLen > 0) {
						try {
							newChannel.close();
							stream.close();
							inputStream.close();
						} catch (Exception e) {
						}
						count++;
						continue aging;
					}
					position = partial+readed;
					unReadLen -= len;
					buffer.rewind();
					int writed=0;
					while((writed+=channel.write(buffer, position+writed))<len){
						System.out.println(fName+":"+writed);
					}
					buffer.rewind();
					readed+=len;
					buffer=unReadLen>=blockL?buffer:ByteBuffer.allocate((int)unReadLen);
				}
				
				completed = true;
				downloader.complete(fName);
				inputStream.close();
				return;
			} catch (Exception e) {
				e.printStackTrace();
				try {
					if (stream != null) {
						stream.flush();
						stream.close();
					}
					if (inputStream != null)
						inputStream.close();

					sleep(5000);
				} catch (Exception e1) {

					e1.printStackTrace();
				}
				System.out.println(fName +" "+e.getMessage()+ " Exception time:"
						+ new Date().toLocaleString());
				count++;
				continue ;
			}
		}

	}
	
	public long length(){
		return readed;
	}

}
